Plane Crashes Dataset Analysis¶
Authors: Luca Del Curto & Pierpaolo Casati¶
In this notebook, we analyze the aviation accident dataset, offering a comprehensive exploration of air travel safety through historical data. The analysis includes data cleaning, exploratory data analysis (EDA), and visualizations that shed light on the evolution of aviation safety over time.
The dataset was found at the following link: https://www.kaggle.com/datasets/abeperez/historical-plane-crash-data
Introduction¶
This analysis explores the aviation accidents dataset to uncover patterns in air travel safety and incident trends. By examining historical records of aircraft accidents, we aim to understand the evolution of aviation safety and identify key factors contributing to incidents. The analysis addresses critical questions such as:
- How has the frequency of aviation accidents changed over time?
- What are the primary causes of aircraft incidents across different eras?
- How have technological and safety improvements impacted accident rates?
- Are there specific regions or types of aircraft more prone to accidents?
Through comprehensive data analysis, we seek to provide insights into the historical context of aviation safety, highlighting the continuous efforts to improve flight safety and reduce the risk of accidents.
Explanation of the Dataset¶
Let's start by looking at the dataset columns.
| Column | Description |
|---|---|
| Date | The date of the crash. |
| Time | The time the crash occurred (if available). |
| Aircraft | The type of aircraft involved in the crash. |
| Operator | The operator of the flight. |
| Registration | The registration number of the aircraft. |
| Flight phase | The phase of the flight during the crash (e.g., landing, takeoff). |
| Flight type | The type of flight (e.g., commercial, cargo). |
| Survivors | The number of survivors in the crash. |
| Crash site | The specific site where the crash occurred. |
| Schedule | The flight schedule (if available). |
| MSN | Manufacturer Serial Number of the aircraft. |
| YOM | Year of Manufacture of the aircraft. |
| Flight no. | The flight number of the aircraft. |
| Crash location | The location of the crash (city or area). |
| Country | The country where the crash occurred. |
| Region | The region within the country of the crash. |
| Crew on board | Number of crew members on board. |
| Crew fatalities | Number of crew fatalities. |
| Pax on board | Number of passengers on board. |
| Pax fatalities | Number of passenger fatalities. |
| Other fatalities | Number of other fatalities (e.g., on the ground). |
| Total fatalities | Total number of fatalities in the crash. |
| Circumstances | Details about the circumstances of the crash. |
| Crash cause | The cause of the crash, if known. |
Step 1: Import Libraries¶
Let's start by loading the required libraries.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio
pio.renderers.default='notebook'
filepath = "/Users/pierpaolocasati/OneDrive/SUPSI/quinto semestre/data science/dataset_aerei"
%cd {filepath}
/Users/pierpaolocasati/Library/CloudStorage/OneDrive-Personale/SUPSI/quinto semestre/data science/dataset_aerei
Step2: Data Loading and Initial Exploration¶
This section focuses on loading the dataset, converting date information, and performing an initial exploration to understand the temporal range and basic characteristics of the aircraft accident records.
df = pd.read_csv("PlaneCrashes.csv")
df['Date'] = pd.to_datetime(df['Date'])
earliest_date = df['Date'].min()
latest_date = df['Date'].max()
time_range = latest_date - earliest_date
print(f"Prima data nel dataset: {earliest_date.strftime('%Y-%m-%d')}")
print(f"Ultima data nel dataset: {latest_date.strftime('%Y-%m-%d')}")
print(f"Range temporale: {time_range.days} giorni ({time_range.days/365.25:.1f} anni)")
print("\nInformazioni sul dataset:")
print(f"Numero totale di record: {len(df)}")
missing_values = df.isnull().sum()
print("\nValori mancanti per colonna:")
print(missing_values[missing_values > 0])
Prima data nel dataset: 1918-05-02 Ultima data nel dataset: 2022-06-03 Range temporale: 38018 giorni (104.1 anni) Informazioni sul dataset: Numero totale di record: 28536 Valori mancanti per colonna: Time 14587 Aircraft 1 Registration 815 Flight phase 638 Flight type 57 Survivors 1297 Crash site 383 Schedule 8946 MSN 4182 YOM 5311 Flight no. 28536 Crash location 12 Country 1 Region 1 Crew on board 24 Crew fatalities 1 Pax on board 54 PAX fatalities 1 Other fatalities 10 Circumstances 25 dtype: int64
Step 3: Data Cleaning¶
To ensure accurate analysis, we need to import and clean the data by handling missing values, duplicates, and inconsistent formatting.
df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Decade'] = (df['Year'] // 10) * 10
df['Season'] = pd.cut(df['Month'],
bins=[0,3,6,9,12],
labels=['Winter', 'Spring', 'Summer', 'Fall'])
df = df.drop('Flight no.', axis=1)
df['Survivors'] = df['Survivors'].map({'Yes': True, 'No': False})
string_columns = ['Aircraft', 'Operator', 'Registration', 'Flight phase',
'Flight type', 'Crash site', 'Country', 'Region', 'Circumstances', 'Crash cause']
for col in string_columns:
df[col] = df[col].str.strip()
df[col] = df[col].str.upper()
numeric_columns = ['Crew on board', 'Crew fatalities', 'Pax on board',
'PAX fatalities', 'Other fatalities', 'Total fatalities']
for col in numeric_columns:
df[col] = df[col].astype(float)
df['Total_aboard'] = df['Crew on board'] + df['Pax on board']
mask = df['Total fatalities'] > df['Total_aboard']
df.loc[mask, ['Total fatalities', 'Crew fatalities', 'PAX fatalities']] = np.nan
df.loc[df['YOM'] > df['Year'], 'YOM'] = np.nan
df['Aircraft_Age'] = df['Year'] - df['YOM']
duplicates = df.duplicated().sum()
if duplicates > 0:
df = df.drop_duplicates()
df.tail(3)
| Date | Time | Aircraft | Operator | Registration | Flight phase | Flight type | Survivors | Crash site | Schedule | ... | Other fatalities | Total fatalities | Circumstances | Crash cause | Year | Month | Decade | Season | Total_aboard | Aircraft_Age | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 28533 | 2022-05-24 | 15H 40M 0S | DE HAVILLAND DHC-3 OTTER | YAKUTAT COASTAL AIRLINES | N703TH | LANDING (DESCENT OR APPROACH) | CHARTER/TAXI (NON SCHEDULED REVENUE FLIGHT) | True | AIRPORT (LESS THAN 10 KM FROM AIRPORT) | Yakutat – Dry Bay | ... | 0.0 | 0.0 | THE SINGLE ENGINE AIRPLANE DEPARTED YAKUTAT ON... | UNKNOWN | 2022 | 5 | 2020 | Spring | 4.0 | 57.0 |
| 28534 | 2022-05-29 | 10H 7M 0S | DE HAVILLAND DHC-6 TWIN OTTER | TARA AIR | 9N-AET | FLIGHT | SCHEDULED REVENUE FLIGHT | False | MOUNTAINS | Pokhara – Jomsom | ... | 0.0 | 22.0 | THE TWIN ENGINE AIRPLANE DEPARTED POKHARA CITY... | HUMAN FACTOR | 2022 | 5 | 2020 | Spring | 22.0 | 43.0 |
| 28535 | 2022-06-03 | 13H 46M 0S | CESSNA 208B GRAND CARAVAN | GOJUMP OCEANSIDE | N7581F | LANDING (DESCENT OR APPROACH) | SKYDIVING / PARATROOPERS | True | AIRPORT (LESS THAN 10 KM FROM AIRPORT) | Oceanside - Oceanside | ... | 0.0 | 1.0 | THE SINGLE ENGINE WAS COMPLETING LOCAL SKYDIVI... | UNKNOWN | 2022 | 6 | 2020 | Spring | 2.0 | 28.0 |
3 rows × 29 columns
Cleaning Process¶
Description of the cleaning process.
| Column | Before Cleaning | Operation | After Cleaning |
|---|---|---|---|
| Date | Mixed formats and missing values | Parsed to datetime, extracted Year, Month, Decade, and Season | Standardized datetime and new temporal features added |
| Flight no. | Only NA values | Dropped column | Column removed |
| Survivors | Categorical ("Yes", "No") | Mapped to boolean | True/False values |
| String Columns | Inconsistent casing and extra spaces | Trimmed spaces and standardized to uppercase | Cleaned and standardized text |
| Numeric Columns | Inconsistent data types | Converted to float | Consistent numeric types |
| Total Fatalities | Invalid values (exceeding total aboard) | Set invalid rows to null | Valid data only |
| YOM | Future years | Set invalid values to null | Valid manufacturing years |
| Aircraft Age | Not available | Computed as Year - YOM | New feature added |
| Duplicates | Multiple duplicate rows | Removed duplicates | Unique rows only |
Step 4: Exploratory Data Analysis (EDA)¶
In this section, we analyze key trends and patterns within the aviation accidents dataset. Through visualizations and descriptive statistics, we aim to uncover insights into accident frequency, causes, and the impact of safety advancements over time.
Evolution of Aircraft Accidents (1918-2022)¶
This visualization depicts the annual number of aircraft accidents from 1918 to 2022. The trend highlights significant changes over time, reflecting the impact of advancements in aviation technology and safety regulations.
yearly_accidents = df[df['Year'] != 2020].groupby('Year').size().reset_index(name='count')
fig = go.Figure()
fig.add_trace(go.Scatter(
x=yearly_accidents['Year'],
y=yearly_accidents['count'],
mode='lines',
name='Incidenti'
))
fig.update_layout(
title='Evolution of Aircraft Accidents (1918-2022)',
xaxis_title='Year',
yaxis_title='Number of Incidents',
template='plotly_white',
hovermode='x',
xaxis=dict(
range=[min(yearly_accidents['Year']) - 5, max(yearly_accidents['Year']) + 5]
)
)
fig.show()
Evolution of Air Safety by Decade¶
This chart provides a decade-wise analysis of aviation safety, showcasing incidents per decade, mortality rates, and the average age of aircraft. It illustrates the interplay between operational safety improvements and technological advancements in the aviation industry.
decade_stats = df.groupby('Decade').agg({
'Total_aboard': 'sum',
'Total fatalities': 'sum',
'Aircraft_Age': 'mean',
'Flight type': 'count'
}).reset_index()
decade_stats = decade_stats[decade_stats['Decade'] != 2020]
decade_stats['mortality_rate'] = (decade_stats['Total fatalities'] / decade_stats['Total_aboard'] * 100)
decade_stats['incidents_per_year'] = decade_stats['Flight type'] / 10
fig = go.Figure()
fig.add_trace(go.Bar(
x=decade_stats['Decade'],
y=decade_stats['incidents_per_year'],
name='Incidents/Decade',
marker_color='lightgray',
opacity=0.7
))
fig.add_trace(go.Scatter(
x=decade_stats['Decade'],
y=decade_stats['mortality_rate'],
name='Mortality Rate (%)',
yaxis='y2',
line=dict(color='red', width=3)
))
fig.add_trace(go.Scatter(
x=decade_stats['Decade'],
y=decade_stats['Aircraft_Age'],
name='Average Age Aircraft (Years)',
yaxis='y3',
line=dict(color='blue', width=3, dash='dash')
))
fig.update_layout(
title='Evolution of Air Safety by Decade',
yaxis=dict(
title='Incidents/Decade',
titlefont=dict(color='gray'),
tickfont=dict(color='gray'),
gridcolor='lightgray',
showgrid=True,
gridwidth=1
),
yaxis2=dict(
title='Mortality Rate (%)',
titlefont=dict(color='red'),
tickfont=dict(color='red'),
anchor='free',
overlaying='y',
side='right',
position=1,
showgrid=False
),
yaxis3=dict(
title='Average Age Aircraft',
titlefont=dict(color='blue'),
tickfont=dict(color='blue'),
anchor='free',
overlaying='y',
side='right',
position=0.88,
showgrid=False
),
xaxis=dict(
range=[1905, 2015],
dtick=10,
ticktext=[str(i) for i in range(1910, 2011, 10)],
tickvals=[i for i in range(1910, 2011, 10)],
gridcolor='lightgray',
gridwidth=1,
showgrid=True
),
showlegend=True,
template='plotly_white',
hovermode='x',
width=1000,
height=650,
margin=dict(r=200),
plot_bgcolor='white'
)
fig.show()
Incident Distribution by Country (Top 20)¶
This pie chart represents the percentage distribution of aircraft incidents across the top 20 countries. The size of each slice corresponds to the proportion of incidents, and the color gradient reflects the mortality rate in each country. The chart provides insights into regional disparities in aviation safety.
df_filtered = df[df['Country'] != 'WORLD']
country_stats = df_filtered.groupby(['Country']).agg({
'Aircraft': 'count',
'Total fatalities': 'sum',
'Total_aboard': 'sum'
}).reset_index()
total_incidents = country_stats['Aircraft'].sum()
total_fatalities = country_stats['Total fatalities'].sum()
total_aboard = country_stats['Total_aboard'].sum()
country_stats['incident_percentage'] = (country_stats['Aircraft'] / total_incidents * 100).round(2)
country_stats['fatality_percentage'] = (country_stats['Total fatalities'] / country_stats['Total_aboard'] * 100).round(2)
country_stats = country_stats.nlargest(20, 'incident_percentage')
fig = go.Figure(go.Sunburst(
labels=country_stats['Country'],
parents=[''] * len(country_stats),
values=country_stats['incident_percentage'],
branchvalues='total',
marker=dict(
colors=country_stats['fatality_percentage'],
colorscale='Reds',
showscale=True,
colorbar=dict(title='Mortality Rate (%)')
),
hovertemplate="<b>%{label}</b><br>" +
"% Total Crashes: %{value:.1f}%<br>" +
"Mortality Rate: %{color:.1f}%<br>" +
"<extra></extra>"
))
fig.update_layout(
title='Percentage Distribution of Aircraft Crashes by Country (Top 20).',
width=1000,
height=1000
)
fig.show()
n_removed = len(df) - len(df_filtered)
print(f"Rows removed: {n_removed}")
percent_removed = (n_removed / len(df)) * 100
print(f"Percentage rows removed: {percent_removed:.2f} %")
Rows removed: 596 Percentage rows removed: 2.09 %
Mortality Rate by Phase and Type of Flight¶
This heatmap illustrates the mortality rate for different flight phases and flight types, with the color intensity representing higher rates. The accompanying text provides the number of incidents for each category, offering a comprehensive view of how specific conditions impact safety outcomes.
flight_conditions = df.groupby(['Flight phase', 'Flight type']).agg({
'Aircraft': 'count',
'Total fatalities': 'sum',
'Total_aboard': 'sum'
}).reset_index()
flight_conditions['mortality_rate'] = (flight_conditions['Total fatalities'] / flight_conditions['Total_aboard'] * 100).round(2)
top_types = flight_conditions.groupby('Flight type')['Aircraft'].sum().nlargest(8).index
df['Flight type'] = df['Flight type'].apply(lambda x: x if x in top_types else 'OTHER')
flight_conditions = df.groupby(['Flight phase', 'Flight type']).agg({
'Aircraft': 'count',
'Total fatalities': 'sum',
'Total_aboard': 'sum'
}).reset_index()
flight_conditions['mortality_rate'] = (flight_conditions['Total fatalities'] / flight_conditions['Total_aboard'] * 100).round(2)
heatmap_matrix = flight_conditions.pivot_table(
values='mortality_rate',
index='Flight phase',
columns='Flight type',
aggfunc='mean'
).round(2)
incidents_matrix = flight_conditions.pivot_table(
values='Aircraft',
index='Flight phase',
columns='Flight type',
aggfunc='sum'
)
fig = go.Figure(data=go.Heatmap(
z=heatmap_matrix,
x=heatmap_matrix.columns,
y=heatmap_matrix.index,
colorscale='YlOrRd',
text=incidents_matrix,
texttemplate='%{text} incidents<br>%{z:.1f}% mortality',
textfont={"size": 10},
hoverongaps=False
))
fig.update_layout(
title={
'text': 'Mortality Rate by Phase and Type of Flight.',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'
},
xaxis_title='Type of Flight',
yaxis_title='Flight Phase',
width=1100,
height=800,
template='plotly_white'
)
fig.show()
Causes of Accidents by Operator¶
This stacked bar chart shows the percentage distribution of accident causes for the top 10 operators. The categories include human factors, technical failures, weather conditions, terrorism acts, and other causes. The visualization highlights the varying risk factors and their prevalence across different operators, offering insights into operational safety challenges.
top_operators = df['Operator'].value_counts().head(10).index
filtered_df = df[df['Operator'].isin(top_operators)]
filtered_df.loc[:, 'Crash cause'] = filtered_df['Crash cause'].replace({'UNKNOWN': 'OTHER CAUSES'})
cause_distribution = (
filtered_df.groupby(['Operator', 'Crash cause'])
.size()
.unstack(fill_value=0)
)
cause_order = ['OTHER CAUSES', 'HUMAN FACTOR', 'TECHNICAL FAILURE', 'WEATHER', 'TERRORISM ACT, HIJACKING, SABOTAGE']
cause_distribution = cause_distribution[cause_order]
cause_distribution_normalized = cause_distribution.div(cause_distribution.sum(axis=1), axis=0) * 100
colors = {
'OTHER CAUSES': '#A9A9A9',
'HUMAN FACTOR': '#1f77b4',
'TECHNICAL FAILURE': '#ff7f0e',
'WEATHER': '#17becf',
'TERRORISM ACT, HIJACKING, SABOTAGE': '#d62728'
}
fig = go.Figure()
for cause in reversed(cause_order):
fig.add_trace(go.Bar(
x=cause_distribution_normalized.index,
y=cause_distribution_normalized[cause],
name=cause,
marker_color=colors[cause]
))
fig.update_layout(
title='Percentage Distribution of Causes of Accidents by Operator',
xaxis_title='Operator',
yaxis_title='Percentage of Incidents (%)',
barmode='stack',
template='plotly_white',
height=700,
width=1100,
yaxis=dict(ticksuffix='%')
)
fig.show()
Normalized Plane Crashes by Country per Decade¶
This area chart displays the normalized percentage of plane crashes by country over each decade. It highlights the contribution of the top 10 countries (9 countries + world) to global crashes, providing insights into how the distribution of incidents has evolved regionally across time.
crashes_by_country_decade = df.groupby(['Country', 'Decade']).size().reset_index(name='Crashes')
top_countries = df['Country'].value_counts().head(10).index.tolist()
crashes_by_country_decade_filtered = crashes_by_country_decade[crashes_by_country_decade['Country'].isin(top_countries)]
crashes_normalized = crashes_by_country_decade_filtered.pivot(index='Decade', columns='Country', values='Crashes')
crashes_normalized = crashes_normalized.fillna(0)
crashes_normalized = crashes_normalized.div(crashes_normalized.sum(axis=1), axis=0) * 100
fig = go.Figure()
top_countries = ['WORLD'] + sorted([c for c in top_countries if c != 'WORLD'])
for country in reversed(top_countries):
fig.add_trace(go.Scatter(
x=crashes_normalized.index,
y=crashes_normalized[country],
mode='lines',
stackgroup='one',
name=country,
line=dict(color='lightgray' if country == 'WORLD' else None)
))
fig.update_layout(
title='Normalized Plane Crashes by Country per Decade',
xaxis_title='Decade',
yaxis_title='Normalized Crashes (%)',
xaxis_tickvals=crashes_normalized.index[::2],
template='plotly_white',
height= 500,
width = 1000
)
fig.show()
Percentage Distribution of Causes of Accidents by Country¶
This stacked bar chart visualizes the percentage distribution of accident causes across the top 15 countries (14 countries + world). Each category, including human factors, technical failures, weather, terrorism acts, and other causes, is represented as a proportion of total incidents for each country. The chart provides a detailed view of how different factors contribute to aviation incidents globally.
top_countries = df['Country'].value_counts().head(15).index
filtered_df = df[df['Country'].isin(top_countries)]
filtered_df.loc[:, 'Crash cause'] = filtered_df['Crash cause'].replace({'UNKNOWN': 'OTHER CAUSES'})
cause_distribution = (
filtered_df.groupby(['Country', 'Crash cause'])
.size()
.unstack(fill_value=0)
)
cause_order = ['OTHER CAUSES', 'HUMAN FACTOR', 'TECHNICAL FAILURE', 'WEATHER', 'TERRORISM ACT, HIJACKING, SABOTAGE']
cause_distribution = cause_distribution[cause_order]
cause_distribution_normalized = cause_distribution.div(cause_distribution.sum(axis=1), axis=0) * 100
colors = {
'OTHER CAUSES': '#A9A9A9',
'HUMAN FACTOR': '#1f77b4',
'TECHNICAL FAILURE': '#ff7f0e',
'WEATHER': '#17becf',
'TERRORISM ACT, HIJACKING, SABOTAGE': '#d62728'
}
fig = go.Figure()
for cause in reversed(cause_order):
fig.add_trace(go.Bar(
x=cause_distribution_normalized.index,
y=cause_distribution_normalized[cause],
name=cause,
marker_color=colors[cause]
))
fig.update_layout(
title='Percentage Distribution of Causes of Accidents by Country',
xaxis_title='Country',
yaxis_title='Percentage of Incidents (%)',
barmode='stack',
template='plotly_white',
height=700,
width=1100,
yaxis=dict(ticksuffix='%'),
xaxis=dict(tickangle=-45)
)
fig.show()
Evolution of Crash Causes Over Time¶
This line chart tracks the evolution of crash causes across decades, showcasing the changing contribution of factors such as human errors, technical failures, weather, and terrorism. Each line represents a cause, providing a clear view of how the relative importance of each factor has shifted over time.
df['Crash cause'] = df['Crash cause'].replace('UNKNOWN', 'OTHER CAUSES')
cause_evolution = df[df['Decade'] != 2020].groupby(['Decade', 'Crash cause']).size().reset_index(name='count')
cause_evolution['percentage'] = cause_evolution.groupby('Decade')['count'].transform(
lambda x: x/x.sum() * 100
)
fig = go.Figure()
colors = {
'OTHER CAUSES': '#A9A9A9',
'HUMAN FACTOR': '#1f77b4',
'TECHNICAL FAILURE': '#ff7f0e',
'WEATHER': '#17becf',
'TERRORISM ACT, HIJACKING, SABOTAGE': '#d62728'
}
order = [
'HUMAN FACTOR',
'TECHNICAL FAILURE',
'WEATHER',
'TERRORISM ACT, HIJACKING, SABOTAGE',
'OTHER CAUSES'
]
for cause in order:
mask = cause_evolution['Crash cause'] == cause
fig.add_trace(go.Scatter(
x=cause_evolution[mask]['Decade'],
y=cause_evolution[mask]['percentage'],
name=cause,
mode='lines+markers',
line=dict(
width=3,
color=colors.get(cause, 'black')
),
marker=dict(
size=8,
symbol='circle'
),
hovertemplate="<b>%{x}</b><br>" +
f"Causa: {cause}<br>" +
"Percentuale: %{y:.1f}%<br>" +
"<extra></extra>"
))
fig.update_layout(
title='Evolution of crash causes over time',
xaxis_title='Decade',
yaxis_title='Percentage (%)',
template='plotly_white',
height=700,
width=1100,
showlegend=True,
legend=dict(
yanchor="top",
y=0.99,
xanchor="right",
x=1.4
),
hovermode='x unified',
xaxis=dict(
showgrid=True,
gridwidth=1,
gridcolor='lightgray',
dtick=10
),
yaxis=dict(
showgrid=True,
gridwidth=1,
gridcolor='lightgray'
)
)
fig.show()
Step 5: Conclusion¶
This analysis provides actionable insights for aviation safety improvements by examining historical aircraft crash data. The findings offer a deeper understanding of accident trends, causes, and their distribution across regions, operators, and flight conditions.
Key takeaways include:
- Decreasing Accident Rates: A clear downward trend in aviation accidents over the decades underscores the success of technological innovations and stricter safety regulations.
- Human Factors and Technical Failures: These remain the leading causes of accidents, emphasizing the need for continued investment in training, system reliability, and human-machine interaction.
- Regional Variations: Disparities in incident rates across countries highlight areas requiring targeted safety interventions and policy enhancements.
- Flight Phases and Types: The analysis revealed critical phases, such as flight, that demand focused safety measures to minimize risks.
- Evolution of Regional Contributions: Normalized crash data highlights shifting contributions of countries to global aviation incidents, reflecting regional disparities in aviation safety and improvements over time.
By leveraging these insights, aviation stakeholders can identify areas for strategic improvement, prioritize safety enhancements, and support efforts to mitigate risks effectively, fostering a safer global aviation industry.